package com.xiaoshuidi.cloud.framework.systemevent.config;

import com.xiaoshuidi.cloud.framework.systemevent.core.LeaseSystemEventConstants;
import org.springframework.boot.context.event.ApplicationContextInitializedEvent;
import org.springframework.cloud.bus.BusConstants;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.*;

import java.util.HashMap;
import java.util.Map;

public class LeaseSystemEventEnvironmentPostProcess implements ApplicationListener<ApplicationContextInitializedEvent> {
        static final String OVERRIDES_PROPERTY_SOURCE_NAME = "leaseSystemEventOverridesProperties";
        private static final String FN_DEF_PROP = "spring.cloud.stream.function.definition";

        public void postProcessEnvironment(ConfigurableEnvironment environment) {
            Map<String, Object> overrides = new HashMap<>();
            String definition = LeaseSystemEventConstants.CONSUMER;
            if (environment.containsProperty(FN_DEF_PROP)) {
                String property = environment.getProperty(FN_DEF_PROP);
                if (property != null && property.contains(LeaseSystemEventConstants.CONSUMER)) {
                    // in the case that EnvironmentPostProcessor are run more than once.
                    return;
                }
                definition = property + ";" + definition;
            }
            overrides.put(FN_DEF_PROP, definition);
            String applicationName = environment.getProperty("spring.application.name");
            overrides.put("spring.cloud.stream.function.bindings." + LeaseSystemEventConstants.CONSUMER + "-in-0", LeaseSystemEventConstants.INPUT);
            overrides.put("spring.cloud.stream.bindings." + LeaseSystemEventConstants.OUTPUT + ".destination", LeaseSystemEventConstants.DESTINATION);
            overrides.put("spring.cloud.stream.bindings." + LeaseSystemEventConstants.INPUT + ".destination", LeaseSystemEventConstants.DESTINATION);
            overrides.put("spring.cloud.stream.bindings." + LeaseSystemEventConstants.INPUT + ".group", "lease-bus-group-" + applicationName);
            overrides.put("spring.cloud.stream.rocketmq.bindings." + LeaseSystemEventConstants.INPUT + ".consumer.group", "lease-bus-group-" + applicationName);
            addOrReplace(environment.getPropertySources(), overrides, OVERRIDES_PROPERTY_SOURCE_NAME, true);
        }

        public static void addOrReplace(MutablePropertySources propertySources, Map<String, Object> map,
                                        String propertySourceName, boolean first) {
            MapPropertySource target = null;
            if (propertySources.contains(propertySourceName)) {
                PropertySource<?> source = propertySources.get(propertySourceName);
                if (source instanceof MapPropertySource) {
                    target = (MapPropertySource) source;
                    target.getSource().putAll(map);
                }
            }
            if (target == null) {
                target = new MapPropertySource(propertySourceName, map);
            }
            if (propertySources.contains(propertySourceName)) {
                propertySources.remove(propertySourceName);
            }
            if (first) {
                propertySources.addFirst(target);
            } else {
                propertySources.addLast(target);
            }
        }

        @Override
        public void onApplicationEvent(ApplicationContextInitializedEvent event) {
            Environment environment = event.getApplicationContext().getEnvironment();
            postProcessEnvironment((ConfigurableEnvironment) environment);
        }
    }

